﻿using System;
using System.Linq;
using System.Net;
using System.Windows;
using Microsoft.Phone.Controls;
using System.Device.Location;
using System.Xml.Linq;
using Coding4Fun.Phone.Controls;
using Microsoft.Phone.Controls.Maps;

namespace geopg_wp7
{
    public partial class LocationSearchPage : PhoneApplicationPage
    {
        // URI for Google Maps reverse-geocoding
        public string baseUri = "http://maps.googleapis.com/maps/api/geocode/xml?latlng={0},{1}&sensor=false";
        public string baseUri2 = "http://maps.googleapis.com/maps/api/geocode/xml?address={0}&sensor=false";

        public GeoCoordinate coord;

        Double longitude;
        Double latitude;
        Double zoomlevel;

        public LocationSearchPage()
        {
            InitializeComponent();
            zoomlevel = 16;
            // Create Location-Service
            GeoCoordinateWatcher g = new GeoCoordinateWatcher();
            // Retry starting Service each second
            g.TryStart(false, TimeSpan.FromMilliseconds(1000));
            // Set global variable
            GlobalVariables.g = g;
            // Get current location
            coord = g.Position.Location;
            longitude = coord.Longitude;
            latitude = coord.Latitude;
            longitude_Text.Text = longitude.ToString(System.Globalization.CultureInfo.InvariantCulture);
            latitude_Text.Text = latitude.ToString(System.Globalization.CultureInfo.InvariantCulture);
            /*longitude_Text.Text = String.Format("{0:0.000000}", longitude);
            latitude_Text.Text = String.Format("{0:0.000000}", latitude);*/

            //
            //* REVERSE GEOCODING (LOCATION IN LAT/LONG TO ADDRESS_DATA)
            //
            // <<< BING_MAPS_VERSION >>>
            /*ReverseGeocodeRequest reverseGeocodeRequest = new ReverseGeocodeRequest();
            // Set the credentials using a valid Bing Maps key
            reverseGeocodeRequest.Credentials = new Microsoft.Phone.Controls.Maps.Credentials();
            reverseGeocodeRequest.Credentials.ApplicationId = "AnXpqYyuIM_BTFPnNLflUyJGduYKh-PHG9Zssbt9IqbM533GKYse_Iu8UCRJ5srr";            
            // Set the point to use to find a matching address
            GeocodeLocation point = new GeocodeLocation();
            point.Latitude = coord.Latitude;
            point.Longitude = coord.Longitude;
            reverseGeocodeRequest.Location = point;
            // Make the reverse geocode request
            GeocodeServiceClient geocodeService = new GeocodeServiceClient(new System.ServiceModel.BasicHttpBinding(), new System.ServiceModel.EndpointAddress("http://dev.virtualerath.net/webservices/v1/gecodeservice/geocodeservice.svc?wsdl"));
            geocodeService.ReverseGeocodeCompleted += new EventHandler<ReverseGeocodeCompletedEventArgs>(geocodeService_ReverseGeocodeCompleted);
            geocodeService.ReverseGeocodeAsync(reverseGeocodeRequest);*/
            RetrieveFormatedAddress(latitude_Text.Text, longitude_Text.Text);
            map.SetView(coord, zoomlevel);
        }

        void RetrieveFormatedLatLng(string add)
        {
            string requestUri2 = string.Format(baseUri2, add);

            WebClient wc2 = new WebClient();
            wc2.DownloadStringCompleted += new DownloadStringCompletedEventHandler(wc_DownloadStringCompletedLatLng);
            wc2.DownloadStringAsync(new Uri(requestUri2));
        }

        // need to add own wc_DownloadStringCompleted for output of <lat> and <lng> of XML-File
        void RetrieveFormatedAddress(string lat, string lng)
        {
            string requestUri = string.Format(baseUri, lat, lng);

            WebClient wc = new WebClient();
            wc.DownloadStringCompleted += new DownloadStringCompletedEventHandler(wc_DownloadStringCompletedAdd);
            wc.DownloadStringAsync(new Uri(requestUri));
        }

        void wc_DownloadStringCompletedLatLng(object sender, DownloadStringCompletedEventArgs e)
        {
            var xmlElm = XElement.Parse(e.Result);

            var status = (from elm in xmlElm.Descendants()
                          where elm.Name == "status"
                          select elm).FirstOrDefault();
            //MessageBox.Show(status.ToString());
            if (status.Value.ToLower() == "ok")
            {
                var res1 = (from elm in xmlElm.Descendants()
                           where elm.Name == "lat"
                           select elm).FirstOrDefault();
                var res2 = (from elm in xmlElm.Descendants()
                            where elm.Name == "lng"
                            select elm).FirstOrDefault();
                // Needs to be changed, when we take own variables
                //MessageBox.Show("Geocode for: '1600 Amphitheatre Pkwy, Mountain View, CA 94043, USA' is \n" + "Latitude: " + res1.Value + " - Longitude: " + res2.Value);
                latitude_Text.Text = res1.Value;
                longitude_Text.Text = res2.Value;
                coord = new GeoCoordinate(double.Parse(latitude_Text.Text), double.Parse(longitude_Text.Text));
                // Navigate Bing-Maps to current Location (coordinates, zoomLevel)
                map.SetView(coord, zoomlevel);
            }
            else
            {
                addressTextBlock.Text = "No Address Found";
            }
        }

        void wc_DownloadStringCompletedAdd(object sender, DownloadStringCompletedEventArgs e2)
        {
            var xmlElm2 = XElement.Parse(e2.Result);

            var status2 = (from elm in xmlElm2.Descendants()
                          where elm.Name == "status"
                          select elm).FirstOrDefault();
            //MessageBox.Show(status.ToString());
            if (status2.Value.ToLower() == "ok")
            {
                var res2 = (from elm in xmlElm2.Descendants()
                           where elm.Name == "formatted_address"
                           select elm).FirstOrDefault();
                addressTextBlock.Text = res2.Value;
            }
            else
            {
                addressTextBlock.Text ="No Address Found";
            }
        }

        private void zoomIn_Click(object sender, EventArgs e)
        {
            double zoom;
            zoom = map.ZoomLevel;
            map.ZoomLevel = ++zoom;
        }

        private void zoomOut_Click(object sender, EventArgs e)
        {
            double zoom;
            zoom = map.ZoomLevel;
            map.ZoomLevel = --zoom;
        }

        private void searchButton_Click(object sender, EventArgs e)
        {
            NavigationService.Navigate(new Uri("//LocalPicturesPage.xaml", UriKind.Relative));
        }

        private void login_Click(object sender, EventArgs e)
        {
            NavigationService.Navigate(new Uri("//LoginPage.xaml", UriKind.Relative));
        }

        private void mainPage_Click(object sender, EventArgs e)
        {
            NavigationService.Navigate(new Uri("//MainPage.xaml", UriKind.Relative));
        }

        private void localPictures_Click(object sender, EventArgs e)
        {
            NavigationService.Navigate(new Uri("//LocalPicturesPage.xaml", UriKind.Relative));
        }

        private void settings_Click(object sender, EventArgs e)
        {
            NavigationService.Navigate(new Uri("//SettingsPage.xaml", UriKind.Relative));
        }

        private void info_Click(object sender, EventArgs e)
        {
            NavigationService.Navigate(new Uri("//InfoPage.xaml", UriKind.Relative));
        }

        private void findButton_Click(object sender, RoutedEventArgs e)
        {
            // Format: "Straße, Stadt, PLZ, Land" für deutsche Gebiete (Land nicht zwingen notwendig)
            RetrieveFormatedLatLng(addressTextBlock.Text);
        }

        private void MapStyle_Click(object sender, RoutedEventArgs e)
        {
            if (map.Mode is AerialMode)
                map.Mode = new RoadMode();
            else
                map.Mode = new AerialMode();
        }
    }
}